package com.xk857.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xk857.entities.SysMenu;
import com.xk857.entities.SysUser;
import com.xk857.feign.IFeignArticleController;
import com.xk857.feign.IFeignForumController;
import com.xk857.feign.req.UserInfoREQ;
import com.xk857.system.mapper.SysUserMapper;
import com.xk857.system.req.RegisterREQ;
import com.xk857.system.req.SysUserCheckPasswordREQ;
import com.xk857.system.req.SysUserREQ;
import com.xk857.system.req.SysUserUpdatePasswordREQ;
import com.xk857.system.service.ISysUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xk857.util.aliyun.SMSUtils;
import com.xk857.util.base.Result;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 用户信息表 服务实现类
 * @author CV大魔王
 * @since 2021-02-25
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Resource
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private IFeignArticleController feignArticleController;

    @Autowired
    private IFeignForumController feignForumController;

    @Override
    public IPage<SysUser> queryPage(SysUserREQ req) {
        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
        // 条件查询
        if (StringUtils.isNotEmpty(req.getUsername())) {
            wrapper.like("username", req.getUsername());
        }
        if (StringUtils.isNotEmpty(req.getMobile())) {
            wrapper.like("mobile", req.getMobile());
        }
        if (StringUtils.isNotEmpty(req.getCard())) {
            wrapper.eq("card", req.getCard());
        }
        wrapper.orderByDesc("update_date");
        return baseMapper.selectPage(req.getPage(), wrapper);
    }


    @CachePut(value = "user_role_ids",key = "#id")
    @Override
    public List<String> findRoleIdsById(String id) {
        return baseMapper.findRoleIdsById(id);
    }


    @CacheEvict(value = "user_role_ids",key = "#userId")
    @Transactional //进行事务管理
    @Override
    public Result saveUserRole(String userId, List<String> roleIds) {
        // 1. 先删除用户角色关系表数据
        baseMapper.deleteUserRoleByUserId(userId);
        // 2. 再保存新的用户角色关系数据
        if (CollectionUtils.isNotEmpty(roleIds)) {
            baseMapper.saveUserRole(userId, roleIds);
        }
        return Result.ok();
    }


    @Override
    public Result deleteById(String id) {
        // 将 `is_enabled` 状态更新为 0 表示删除
        SysUser sysUser = baseMapper.selectById(id);
        if (sysUser == null) {
            return Result.error("用户不存在，删除失败");
        }
        sysUser.setIsEnabled(0); // 0 删除，1 可用
        sysUser.setUpdateDate(new Date());
        baseMapper.updateById(sysUser);
        return Result.ok();
    }

    @Override
    public Result checkPassword(SysUserCheckPasswordREQ req) {
        if (StringUtils.isEmpty(req.getUserId())) {
            return Result.error("用户ID不能为空,请重试");
        }
        if (StringUtils.isEmpty(req.getOldPassword())) {
            return Result.error("原密码不能为空,请重试");
        }
        SysUser sysUser = baseMapper.selectById(req.getUserId());
        if (sysUser == null) {
            return Result.error("用户不存在,请重试");
        }
        if (!passwordEncoder.matches(req.getOldPassword(), sysUser.getPassword())) {
            return Result.error("原密码输入错误");
        }
        return Result.ok();
    }

    @Override
    public Result updatePassword(SysUserUpdatePasswordREQ req) {
        if (StringUtils.isEmpty(req.getUserId())) {
            return Result.error("用户ID不能为空,请重试");
        }
        if (StringUtils.isEmpty(req.getNewPassword())) {
            return Result.error("新密码不能为空,请重试");
        }
        if (StringUtils.isEmpty(req.getRepPassword())) {
            return Result.error("确认密码不能为空,请重试");
        }
        if (!req.getNewPassword().equals(req.getRepPassword())) {
            return Result.error("密码不一致,请重试");
        }
        SysUser sysUser = baseMapper.selectById(req.getUserId());
        if (sysUser == null) {
            return Result.error("用户不存在,请重试");
        }
        // 旧密码
        if (StringUtils.isNotEmpty(req.getOldPassword())) {
            if (!passwordEncoder.matches(req.getOldPassword(), sysUser.getPassword())) {
                return Result.error("原密码输入错误");
            }
        }
        // 新密码加密
        sysUser.setPassword(passwordEncoder.encode(req.getNewPassword()));
        baseMapper.updateById(sysUser);
        return Result.ok();
    }


    @CacheEvict(value = "user_username",key = "#sysUser.username")
    @Transactional
    @Override
    public Result update(SysUser sysUser) {
        // 1. 查询原用户信息
        SysUser user = baseMapper.selectById(sysUser.getId());
        if (user == null) {
            return Result.error("更新的用户不存在");
        }
        // 2. 判断更新的信息中昵称和头像是否被改变
        if (!StringUtils.equals(sysUser.getNickName(), user.getNickName()) || !StringUtils.equals(sysUser.getImageUrl(), user.getImageUrl())) {
            // 其中一个不相等，则更新用户信息
            // 2.1 调用文章微服务接口更新用户信息
            UserInfoREQ req =
                    new UserInfoREQ(sysUser.getId(), sysUser.getNickName(),
                            sysUser.getImageUrl());
            feignArticleController.updateUserInfo(req);
            // 2.2 调用问答微服务接口更新用户信息
            feignForumController.updateUserInfo(req);
        }
        // 3. 更新用户信息表
        sysUser.setUpdateDate(new Date());
        baseMapper.updateById(sysUser);
        return Result.ok();
    }

    @Override
    public Integer getUserTotal() {
        // 帐户是否可用(1 可用，0 删除用户)
        return baseMapper.selectCount(new QueryWrapper<SysUser>().eq("is_enabled", 1));
    }

    @Override
    public boolean checkUsername(String username) {
        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        SysUser sysUser = baseMapper.selectOne(wrapper);
        // 查询到则存在，存在 data=true 已被注册，不存在 data=false 未被注册
        return sysUser != null;
    }

    @Override
    public Result register(RegisterREQ req) {
        if (StringUtils.isEmpty(req.getUsername())) {
            return Result.error("手机号不能为空，请重试");
        }
        if (StringUtils.isEmpty(req.getPassword())) {
            return Result.error("密码不能为空，请重试");
        }
        if (StringUtils.isEmpty(req.getRepPassword())) {
            return Result.error("确认密码不能为空，请重试");
        }
        if (!StringUtils.equals(req.getPassword(), req.getRepPassword())) {
            return Result.error("两次输入的密码不一致");
        }
        boolean flag = this.checkUsername(req.getUsername());
        if (flag) {
            return Result.error("用户已被注册，请更换个用户名");
        }
        String uuid = req.getUuid();
        if ("".equals(uuid)) {
            return Result.error("验证码有误！");
        }
        String code = redisTemplate.opsForValue().get(uuid);
        if ("".equals(code)) {
            return Result.error("验证码过期！");
        }
        if (!code.equals(req.getCode())) {
            return Result.error("验证码错误！");
        }
        // 删除缓存
        redisTemplate.delete(uuid);
        // 校验都通过，新增用户信息
        SysUser sysUser = new SysUser();
        sysUser.setUsername(req.getUsername());
        // 默认昵称和用户名一样
        sysUser.setNickName(req.getUsername());
        sysUser.setPassword(passwordEncoder.encode(req.getPassword()));
        // 提交用户信息
        this.save(sysUser);
        return Result.ok("注册成功");
    }


    @CachePut(value = "user_username",key = "#username")
    @Override
    public SysUser findByUsername(String username) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public Result sendMsg(String phone) {
        // 生成验证码
        Integer code =(int)((Math.random()*9+1)*100000);
        // 发送短信
        SMSUtils smsUtils = new SMSUtils();
        smsUtils.SendMsg(phone,SMSUtils.REGISTER_CODE, String.valueOf(code));
        // 生成uuid
        String uuid = String.valueOf(UUID.randomUUID());
        // 存入redis
        redisTemplate.opsForValue().set(uuid, String.valueOf(code));
        // 设置5分钟过期时间
        redisTemplate.expire(uuid, 300, TimeUnit.SECONDS);
        Map<String, Object> result = new HashMap<String, Object>(1) {{
            put("uuid", uuid);
        }};
        return Result.ok(result);
    }

    @Override
    public Result sendMsgChangePwd(String phone) {
        // 生成验证码
        Integer code =(int)((Math.random()*9+1)*100000);
        // 发送短信
        SMSUtils smsUtils = new SMSUtils();
        smsUtils.SendMsg(phone,SMSUtils.REGISTER_CODE, String.valueOf(code));
        // 生成uuid
        String uuid = String.valueOf(UUID.randomUUID());
        // 存入redis
        redisTemplate.opsForValue().set(phone+uuid, String.valueOf(code));
        // 设置5分钟过期时间
        redisTemplate.expire(phone+uuid, 300, TimeUnit.SECONDS);
        Map<String, Object> result = new HashMap<String, Object>(1) {{
            put("uuid", uuid);
        }};
        return Result.ok(result);
    }

    @Override
    public Result changePassword(RegisterREQ req) {
        if (StringUtils.isEmpty(req.getUsername())) {
            return Result.error("手机号不能为空，请重试");
        }
        if (StringUtils.isEmpty(req.getPassword())) {
            return Result.error("密码不能为空，请重试");
        }
        if (StringUtils.isEmpty(req.getRepPassword())) {
            return Result.error("确认密码不能为空，请重试");
        }
        if (!StringUtils.equals(req.getPassword(), req.getRepPassword())) {
            return Result.error("两次输入的密码不一致");
        }
        boolean flag = this.checkUsername(req.getUsername());
        if (!flag) {
            return Result.error("您尚未注册，请注册");
        }
        String uuid = req.getUuid();
        if ("".equals(uuid)) {
            return Result.error("验证码有误！");
        }
        String code = redisTemplate.opsForValue().get(req.getUsername()+uuid);
        if ("".equals(code)) {
            return Result.error("验证码过期！");
        }
        if (!code.equals(req.getCode())) {
            return Result.error("验证码错误！");
        }
        // 删除缓存
        redisTemplate.delete(uuid);
        // 校验都通过，更改用户信息
        SysUser sysUser = new SysUser();
        sysUser.setUsername(req.getUsername());
        sysUser = baseMapper.selectOne(new QueryWrapper<>(sysUser));
        // 默认昵称和用户名一样
        sysUser.setPassword(passwordEncoder.encode(req.getPassword()));
        // 提交用户信息
        baseMapper.updateById(sysUser);
        return Result.ok("修改密码成功");
    }

    @Override
    public SysUser findUserById(String id) {
        return baseMapper.selectById(id);
    }

    @Override
    public SysUser findByCard(String card) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("card",card);
        return baseMapper.selectOne(queryWrapper);
    }
}
